﻿// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "pch.h"
#include <shellapi.h>
#include "minhook/MinHook.h"
#pragma comment(lib,"minhook/libMinHook.x64.lib") 
#include <time.h>
#include <stdlib.h>

#include<stdio.h>
#include<Winsock2.h>
#include<time.h>
#include<string.h>
#pragma warning(disable:4996)
#pragma comment(lib,"ws2_32.lib")

#define USER_ERROR -1


//更新时间 - 2024年6月16日

//3S评分 地址
DWORD64 threeS_addr = 0x1451A5CBE;
//自动翻牌 地址(CE地址+1字节)
BYTE* fp_addr = (BYTE*)0x145E1C05F;
//无限聚集物品 地址
DWORD64 wuxianjw_addr = 0x14503A3BE;
//房间编号 地址
DWORD64 FJBH = 0x14C4160D0;
//空白地址+256
DWORD64 KBDZ = 0x13FE52256;
//过图CALL地址
DWORD64 GTCALL = 0x14419E250;
//技能CALL
DWORD64 JNCALL = 0x144DADFF0;
//人物剩余疲劳值
int* pl_sy = (int*)0x14CD36B0C;
//游戏状态 1城镇 2选择地图 3游戏内
int* gametype = (int*)0x14BEEB490;
//物品入包
char* rb = (char*)0x1451727CF;


int pf = 2866669;//评分

void socks_start();

DWORD oldProtect;

DWORD WINAPI func(PVOID param);
DWORD WINAPI rejian(PVOID param);
DWORD WINAPI sjpf(PVOID param);
DWORD WINAPI tx(PVOID param);

void BH_S(LPVOID addr);
void BH_E(LPVOID addr);

HRESULT threeS_detour();
HRESULT wuxianjw_detour();
HRESULT jn_detour();

EXTERN_C void threeS();
EXTERN_C void wuxianjw();
EXTERN_C void gtcall(DWORD64,int,DWORD64,int,DWORD64);
EXTERN_C void jn();


typedef void(__stdcall* gttcall) (DWORD64,int, DWORD64, DWORD64,DWORD64);
gttcall GTCALLC= (gttcall)(DWORD_PTR*)GTCALL;


typedef HRESULT(* Func)();

Func threeS_original;
Func wuxianjw_original;
Func jn_original;

void gt(int num);


extern "C" int GetRangeRandom();

int GetRangeRandom()
{
    return pf;
}

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                     )
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, 0, func, 0, 0, NULL);
        //CreateThread(NULL, 0, rejian, 0, 0, NULL);
        CreateThread(NULL, 0, sjpf, 0, 0, NULL);
        CreateThread(NULL, 0, tx, 0, 0, NULL);
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

DWORD WINAPI tx(PVOID param) {

    socks_start();

    return 0;

}



DWORD WINAPI sjpf(PVOID param) {


    while (true) {

        int min = 1000000;
        int max = 3000000;
        int t = (double)rand() / (RAND_MAX + 1) * (max - min) + min;
        pf = t;
        Sleep(10000);
    }

    return 0;

}


DWORD WINAPI rejian(PVOID param) {

    while (true)
    {
        Sleep(0);
        if (GetAsyncKeyState(VK_MENU) & GetAsyncKeyState(VK_LEFT) & 0x8000) {
            gt(0);
            Sleep(200);
        }
        else if (GetAsyncKeyState(VK_MENU) & GetAsyncKeyState(VK_RIGHT) & 0x8000) 
        {
            gt(1);
            Sleep(200);
        }
        else if (GetAsyncKeyState(VK_MENU) & GetAsyncKeyState(VK_UP) & 0x8000) {
            gt(2);
            Sleep(200);
        }
        else if (GetAsyncKeyState(VK_MENU) & GetAsyncKeyState(VK_DOWN) & 0x8000) {
            gt(3);
            Sleep(200);
        }
        else if (GetAsyncKeyState(VK_F7) & 0x8000) {
            ShellExecuteA(0, "runas", "start.bat", "", "zidonghua", 1);
            Sleep(1000);
        }

    }

    return 0;

}


void BH_S(LPVOID addr) {
    bool a = VirtualProtect(addr, 1, PAGE_EXECUTE_READWRITE, &oldProtect);
    if (!a) {
        MessageBoxA(0, "VirtualProtectEx 初始化失败!", "提示", 0);
    }
}
void BH_E(LPVOID addr) {
    bool c = VirtualProtect(addr, 1, oldProtect, &oldProtect);
    if (!c) {
        MessageBoxA(0, "还原失败!", "提示", 0);
    }
}

DWORD WINAPI func(PVOID param) {

    //延时一小会儿防止崩溃
    Sleep(60000);

    //等一会儿以免Hook失败
    //while (!GetModuleHandle(L"clientfx_x64.fxd"));
    
    // Initialize MinHook.
    if (MH_Initialize() != MH_OK)
    {
        return 0;
    }

    //设置自动翻盘 je 144C6D85A 改 jne 144C6D85A
    BH_S(fp_addr); //去掉保护
    *fp_addr = 0x85; //原来是0x84
    BH_E(fp_addr); //还原保护

    //设置自动捡物品
    BH_S(rb); //去掉保护
    *rb = 0x90; //原来是0x84
    *(rb + 1) = 0x90;
    BH_E(rb); //还原保护
    
    //hook 3S评分
    MH_CreateHook((LPVOID)threeS_addr, threeS_detour, (PVOID*)(&threeS_original));
    //无限聚集物品
    MH_CreateHook((LPVOID)wuxianjw_addr, wuxianjw_detour, (PVOID*)(&wuxianjw_original));

    //等一会儿以免Hook失败
    int* JNCALLTEST = (int*)JNCALL;
    while (*JNCALLTEST != 0);
    //hook技能call(代码修改 技能变大)
    MH_CreateHook((LPVOID)JNCALL, jn_detour, (PVOID*)(&jn_original));


    //使能所有Hook
    MH_EnableHook(MH_ALL_HOOKS);

    return 0;
}


HRESULT threeS_detour() {

    
    threeS();

    return threeS_original();
}

HRESULT wuxianjw_detour() {

    wuxianjw();

    return wuxianjw_original();
}


HRESULT jn_detour() {

    jn();

    return jn_original();

}

void gt(int num) {
   // gtcall(FJBH, num, KBDZ, -1, GTCALL);

    DWORD64* a1;
    a1 = (DWORD64*)FJBH;
    a1 = (DWORD64*)(*a1 + 0x20a050);
    a1 = (DWORD64*)(*a1 + 0xc0);

    GTCALLC(*a1, num, KBDZ,-1,0);
}


//外部通信专用
void socks_start()
{

    int ret;
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
    {
        printf("Failed to load Winsock.\n");
        return;
    }

    SOCKET socket_of_server;
    SOCKET socket_of_client;
    socket_of_server = socket(AF_INET, SOCK_STREAM, 0);
    if (socket_of_server == INVALID_SOCKET)
    {
        printf("socket() Failed:%d\n", WSAGetLastError());
        return;
    }

    struct sockaddr_in s_sin;
    s_sin.sin_family = AF_INET;
    s_sin.sin_port = htons(6666);
    s_sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    if (bind(socket_of_server, (LPSOCKADDR)&s_sin, sizeof(s_sin)) == SOCKET_ERROR)
    {
        printf("blind() Failed:%d\n", WSAGetLastError());
        return;
    }
    if (listen(socket_of_server, 5) == SOCKET_ERROR)
    {
        printf("listen() Failed:%d\n", WSAGetLastError());
        return;
    }
    struct sockaddr_in c_sin;
    int c_sin_len = sizeof(c_sin);
    while (1)
    {
        printf("waiting for connect\n");
        socket_of_client = accept(socket_of_server, (SOCKADDR*)&c_sin, &c_sin_len);
        if (socket_of_client == INVALID_SOCKET)
            printf("accept() Failed:%d\n", WSAGetLastError());
        else
        {
            printf("接收到一个连接:%s\r\n", inet_ntoa(c_sin.sin_addr));
            while (1)
            {

                char recvData[200] = { 0 };
                char sendData[200] = { 0 };

                //开始等待指令(阻塞读取信息)
                //printf("读取消息：");
                //recvData[0] = '\0';
                ret = recv(socket_of_client, recvData, 200, 0);
                if (ret <= 0)
                {
                    printf("连接丢失\n");
                    break;
                }

                //printf("%s\n", recvData);
                if (strcmp(recvData, "getpl") == 0) {
                    //发送已使用疲劳值
                    itoa(*pl_sy, sendData, 10);
                }
                else if (strcmp(recvData, "getgametype") == 0) {
                    //发送游戏状态
                    itoa(*gametype, sendData, 10);
                }
                else if (strcmp(recvData, "getroomnum") == 0) {
                    //发送房间编号

                    DWORD64 *py1 = (DWORD64*)FJBH;
                    DWORD64 *py2 = (DWORD64*)(*py1 +0x20A050);

                    DWORD64 *roomnum = (DWORD64*)(*py2 + 0xC0);
                    _ui64toa(*roomnum, sendData, 10);
                }
                else if (strcmp(recvData, "go0") == 0) {
                    gt(0);
                    strcpy(sendData, "ok");
                }
                else if (strcmp(recvData, "go1") == 0) {
                    gt(1);
                    strcpy(sendData, "ok");
                }
                else if (strcmp(recvData, "go2") == 0) {
                    gt(2);
                    strcpy(sendData, "ok");
                }
                else if (strcmp(recvData, "go3") == 0) {
                    gt(3);
                    strcpy(sendData, "ok");
                }
                else {
                    strcpy(sendData, "error");
                }


                send(socket_of_client, sendData, strlen(sendData), 0);

            }
        }

    }

    closesocket(socket_of_server);
    WSACleanup();

    return;
}